#include "lcd.h"
#include <intrins.h>
//#iclude "HZK.h"
#include <REGX52.H>
sbit RS = P0 ^ 5;
sbit EN = P0 ^ 7;
sbit RW = P0 ^ 6;
sbit CS1 = P0 ^ 3;
sbit CS2 = P0 ^ 4;

/************** 判忙函数 **************/
void lcd_r_busy()
{
    P2 = 0x00;
    RS = 0;
    RW = 1;
    EN = 1;
    while (P2 & 0x80)
        ; // 最高位DB7==1，则busy
    EN = 0;
}

/************* LCD写命令函数 *************/
void lcd_w_cmd(uchar value)
{
    lcd_r_busy(); // 每次读写操作前都要忙判断
    RS = 0;
    RW = 0;
    lcd_databus = value;
    EN = 1; // 下降沿锁存写入的数据/命令
    _nop_();
    _nop_();
    EN = 0;
}

/************* LCD写数据  **************/
void lcd_w_data(uchar value)
{
    lcd_r_busy();
    RS = 1;
    RW = 0;
    lcd_databus = value;
    EN = 1; // 下降沿锁存写入的数据/命令
    _nop_();
    _nop_();
    EN = 0;
}

/***************页设置:显示在哪一页******************/
/*************共8页，一页是8行像素点*****************/
void lcd_set_page(uchar page)
{
    page = 0xb8 | page; // 页的首地址为0xb8：page或上0xb8=选择page页
    lcd_w_cmd(page);
}

/************行设置：起始在哪一行********************/
/**********每页共8行，一般从0行开始******************/
void lcd_set_line(uchar sline)
{
    sline = 0xc0 | sline; // 起始行地址为0xc0：sline或上0xc0=选择行
    lcd_w_cmd(sline);
}

/*************起始列设置+像素点选择********************/
/***********每半片共64列，列值不得大于63***************/
void lcd_set_column(uchar column)
{
    column = 0x3f & column; // 与上列的最大值63:0x3f  可得所选列值<63
    column = 0x40 | column; // 得列的首地址
    lcd_w_cmd(column);
}

/*************设置显示的开关********************/
/**********0为关闭显示；1为 开启显示************/
void lcd_on_off(uchar set)
{
    set = 0x3e | set; // =0011 111x----0x3e为关闭显示；0x3f为开启显示
    lcd_w_cmd(set);
}

/*************选择左右半屏显示********************/
/********0-全屏显示；1-左；2-右********************/
/************cs片选端低电平有效********************/
void lcd_cs(uchar sel)
{
    switch (sel)
    {
    case 0:
        CS1 = 0;
        CS2 = 0;
        break; // 全屏显示
    case 1:
        CS1 = 0;
        CS2 = 1;
        break; // 左显示
    case 2:
        CS1 = 1;
        CS2 = 0;
        break; // 右显示
    default:
        break;
    }
}

/*************清屏：选择半屏********************/
/********0-清全屏；1-清左；2-清右***************/
void lcd_clear(uchar sel)
{
    uchar i, j;
    lcd_cs(sel);
    for (i = 0; i < 8; i++)
    {
        lcd_set_page(i);
        lcd_set_column(0);
        for (j = 0; j < 64; j++)
        {
            lcd_w_data(0x00); // 每列全部写0，列地址指针自动+1
        }
    }
}

/****************LCD的初始化********************/
void lcd_init()
{
    lcd_r_busy();
    lcd_cs(0);
    lcd_on_off(0); // 关显示
    lcd_cs(0);
    lcd_on_off(1); // 开显示
    lcd_cs(0);
    lcd_clear(0);    // 清全屏
    lcd_set_line(0); // 起始行设为0
}

/****************16*16像素的汉字显示程序********************/
void display(uchar cs, uchar page, uchar column, uchar *p, uchar index)
{
    uchar i;
    lcd_cs(cs);
    lcd_set_page(page);     // 要在本页写上半个汉字8*16
    lcd_set_column(column); // 选择起始列
    for (i = 0; i < 16; i++)
    {
        lcd_w_data(p[i + index]); // 按列输入上半个汉字的编码8*16
    }
    lcd_set_page(page + 1); // 要在下一页写下半个汉字8*16
    lcd_set_column(column); // 选择起始列
    for (i = 0; i < 16; i++)
    {
        lcd_w_data(p[i + 16 + index]); // 按列输入下半个汉字的编码8*16
    }
}

void display_number(uchar cs, uchar page, uchar column, uchar *p, uchar index)
{
    uchar i;
    lcd_cs(cs);
    lcd_set_page(page);     // 要在本页写上半个汉字8*16
    lcd_set_column(column); // 选择起始列
    for (i = 0; i < 8; i++)
    {
        lcd_w_data(p[i + index]); // 按列输入上半个汉字的编码8*16
    }
    lcd_set_page(page + 1); // 要在下一页写下半个汉字8*16
    lcd_set_column(column); // 选择起始列
    for (i = 0; i < 8; i++)
    {
        lcd_w_data(p[i + 8 + index]); // 按列输入下半个汉字的编码8*16
    }
}